#include "h_ui.h"
#include "h_ui_basic_fonts.h"

#include <stdio.h>

static h_ui_state h_ui_basic_check(h_ui_t *ui_t)
{
    if(!ui_t->ui_draw_point) {
        return ui_draw_point_null;
    }
    if(!ui_t->ui_draw) {
        return ui_draw_null;
    }
    return h_ui_ok;
}

static void h_ui_draw_point_with_check(h_ui_t *ui_t, ui_position_type x, ui_position_type y, ui_color_type color)
{
    if(x >= ui_t->ui_width || y >= ui_t->ui_height) {
        return;
    }
    ui_t->ui_draw_point(x, y, color);
}

h_ui_state h_ui_init(h_ui_t *ui_t, void *draw_point_f, void *draw_f, void *clear_f, ui_position_type width, ui_position_type height)
{
    if(!ui_t) {
        return h_ui_null;
    }
    if(draw_point_f) {
        ui_t->ui_draw_point = draw_point_f;
    }
    if(draw_f) {
        ui_t->ui_draw = draw_f;
    }
    if(clear_f) {
        ui_t->ui_clear = clear_f;
    }
    

    ui_t->ui_width = width;
    ui_t->ui_height = height;

    ui_t->last_x = 0;
    ui_t->last_y = 0;
    return h_ui_ok;
}

h_ui_state h_ui_clear(h_ui_t *ui_t, ui_color_type color)
{
    ui_position_type i, j;
    if(!ui_t) {
        return h_ui_null;
    }
    if(ui_t->ui_clear) {
        ui_t->ui_clear(color);
    } else {
        for(i = 0; i < ui_t->ui_height; i++) {
            for(j = 0; j < ui_t->ui_width; j++) {
                h_ui_draw_point_with_check(ui_t, j, i, color);
            }
        }
    }

    return h_ui_ok;
}

h_ui_state h_ui_moveTo(h_ui_t *ui_t, ui_position_type x, ui_position_type y)
{
    if(!ui_t) {
        return h_ui_null;
    }
    ui_t->last_x = x;
    ui_t->last_y = y;
    return h_ui_ok;
}

h_ui_state h_ui_draw_line(h_ui_t *ui_t, ui_position_type x, ui_position_type y, ui_color_type color)
{
    int dx, dy, sx, sy, err, e2;
    h_ui_state rslt = h_ui_basic_check(ui_t);
    if(rslt) {
        return rslt;
    }
    sx = ui_t->last_x < x ? 1 : -1;
    sy = ui_t->last_y < y ? 1 : -1;

    dx = ui_t->last_x < x ? x - ui_t->last_x : ui_t->last_x - x;
    dy = ui_t->last_y < y ? y - ui_t->last_y : ui_t->last_y - y;

    err = (dx > dy ? dx : -dy) / 2;

    while(1) {
        h_ui_draw_point_with_check(ui_t, ui_t->last_x, ui_t->last_y, color);
        if(ui_t->last_x == x && ui_t->last_y == y) {
            break;
        }
        e2 = err;
        if(e2 > -dx) {
            err -= dy;
            ui_t->last_x += sx;
        }
        if(e2 < dy) {
            err += dx;
            ui_t->last_y += sy;
        }
    }

    // printf("%d, %d\r\n", ui_t->last_x, ui_t->last_y);
    return h_ui_ok;
}


h_ui_state h_ui_draw_pic_with_single_color(h_ui_t *ui_t, ui_position_type x, ui_position_type y, \
                                      ui_position_type width, ui_position_type height, unsigned char *pic)
{
    unsigned char k;
    ui_position_type dx = x, dy = y, i, j;

    unsigned char data;

    h_ui_state rslt = h_ui_basic_check(ui_t);
    if(rslt) {
        return rslt;
    }
    
    for(i = 0; i < height; i++) {
        for(j = 0; j < width; j += 8) {
            data = *pic++;
            for(k = 0; k < 8; k++) {
                h_ui_draw_point_with_check(ui_t, dx, dy, (data & 0x80)?1:0);
                data <<= 1;
                dx++;
                if(dx >= x + width) {
                    dx = x;
                    dy++;
                    if(dy >= y + height) {
                        return h_ui_ok;
                    }
                }
            }
        }
    }

    return h_ui_ok;
}

h_ui_state h_ui_draw_char_with_single_color(h_ui_t *ui_t, ui_position_type x, ui_position_type y, unsigned char data)
{
    return h_ui_draw_pic_with_single_color(ui_t, x, y, 5, 8, (unsigned char *)&h_ui_basic_fonts_5x8[(data - ' ') * 5]);
}

h_ui_state h_ui_draw_string_len_with_single_color(h_ui_t *ui_t, ui_position_type x, ui_position_type y, \
                                                   unsigned char *str, signed int len)
{
    h_ui_state rslt;
    while(len--) {
        rslt = h_ui_draw_char_with_single_color(ui_t, x, y, *str++);
        if(h_ui_ok != rslt) {
            return rslt;
        }
        x += 5;
    }
    return rslt;
}

h_ui_state h_ui_draw_string_len_auto_row_with_single_color(h_ui_t *ui_t, ui_position_type x, ui_position_type y, \
                                                           signed int row_char_max_num, signed int colunm_char_max_num, \
                                                           unsigned char *str, signed int len)
{
    h_ui_state rslt;
    ui_position_type dx = x, dy = y;
    while(len--) {
        rslt = h_ui_draw_char_with_single_color(ui_t, dx, dy, *str++);
        if(h_ui_ok != rslt) {
            return rslt;
        }
        dx += 5;
        if(row_char_max_num > 0) {
            if(dx >= row_char_max_num * 5 + x) {
	            dx = x;
	            dy += 8;
	            if(colunm_char_max_num > 0) {
	                if(dy >= colunm_char_max_num * 8 + y) {
	                    return h_ui_ok;
	                }
	            }
	            
	        }
        }
        
    }
    return rslt;
}



